package com.shop.shopserver.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.shop.shopcommon.properties.ElasticSearchProperties;
import com.shop.shoppojo.entity.Goods;
import com.shop.shopserver.mapper.GoodsMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

import java.util.List;

import static com.shop.shopcommon.constant.ElasticSearchConstant.GOODS_INDEX_NAME;
import static com.shop.shopcommon.constant.ElasticSearchConstant.USER_SEARCH_WORD_INDEX_NAME;
import static com.shop.shopcommon.constant.MessageConstant.INDEX_EXISTS;
import static com.shop.shopcommon.constant.MessageConstant.INDEX_NOT_EXISTS;


@Configuration
@Slf4j
public class ElasticSearchConfig {
    @Autowired
    private ElasticSearchProperties  elasticSearchProperties;
    @Autowired
    private GoodsMapper goodsMapper;

    @Bean
    public RestHighLevelClient elasticsearchClient(ElasticSearchProperties elasticSearchProperties) {
        HttpHost[] httpHosts = elasticSearchProperties.getUris().stream()
                .map(this::parseUriToHttpHost)
                .toArray(HttpHost[]::new);

        return new RestHighLevelClient(RestClient.builder(httpHosts));
    }

    /**
     * 将uris转换为HttpHost
     * @param uri
     * @return HttpHost
     */
    private HttpHost parseUriToHttpHost(String uri) {
        String[] parts = uri.split("://");
        String protocol = parts[0];
        String hostPort = parts[1];
        String[] hostPortParts = hostPort.split(":");
        String host = hostPortParts[0];
        int port = Integer.parseInt(hostPortParts[1]);
        return new HttpHost(host, port, protocol);
    }

    /**
     * 创建所有用户搜索词索引
     */
    @PostConstruct
    public void createUserSearchWordIndex () throws Exception {
        RestHighLevelClient client = elasticsearchClient(elasticSearchProperties);
        // 判断索引是否存在 true存在 false不存在
        GetIndexRequest getIndexRequest = new GetIndexRequest(USER_SEARCH_WORD_INDEX_NAME);
        boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        if (exists) {
            log.info(USER_SEARCH_WORD_INDEX_NAME+INDEX_EXISTS);
            return;
        }
        log.info(USER_SEARCH_WORD_INDEX_NAME+INDEX_NOT_EXISTS);
        // 索引不存在定义索引的映射
        String mapping = "{" +
                "    \"mappings\": {" +
                "        \"properties\": {" +
                "            \"userId\": {" +
                "                \"type\": \"keyword\"" +
                "            }," +
                "            \"searchWord\": {" +
                "                \"type\": \"keyword\"" +
                "            }" +
                "        }" +
                "    }" +
                "}";
        // 创建索引请求
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(USER_SEARCH_WORD_INDEX_NAME)
                .source(mapping, XContentType.JSON);
        // 请求创建索引
        client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
    }

    /**
     * 创建商品索引
     */
    @PostConstruct
    public void createGoodsIndex () throws Exception {
        RestHighLevelClient client = elasticsearchClient(elasticSearchProperties);
        // 判断索引是否存在 true存在 false不存在
        GetIndexRequest getIndexRequest = new GetIndexRequest(GOODS_INDEX_NAME);
        boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        if (exists) {
            log.info(GOODS_INDEX_NAME+INDEX_EXISTS);
            return;
        }
        log.info(GOODS_INDEX_NAME+INDEX_NOT_EXISTS);
        // 索引不存在定义索引的映射
        String mapping = """
        {
            "mappings": {
                "properties": {
                    "id": {
                        "type": "long"
                    },
                    "goodsImage": {
                        "type": "keyword",
                        "index": false
                    },
                    "goodsName": {
                        "type": "text",
                        "analyzer": "ik_max_word"
                    },
                    "goodsPriceMax": {
                        "type": "scaled_float",
                        "scaling_factor": 100
                    },
                    "goodsPriceMin": {
                        "type": "scaled_float",
                        "scaling_factor": 100
                    },
                    "goodsSales": {
                        "type": "integer"
                    },
                    "stockTotal": {
                        "type": "integer"
                    }
                }
            }
        }
        """;

        // 创建索引请求
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(GOODS_INDEX_NAME)
                .source(mapping, XContentType.JSON);
        // 请求创建索引
        client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        log.info("商品索引创建成功");

        // 初始化商品索引
        //获取所有商品数据，用于写入es
        List<Goods> goodsList = goodsMapper.selectList(null);

        //将获取的数据库商品数据，设置到es的goods索引
        BulkRequest bulkRequest = new BulkRequest();
        for (Goods goods : goodsList) {
            IndexRequest indexRequest = new IndexRequest(GOODS_INDEX_NAME)
                    .id(goods.getId().toString())
                    .source(new ObjectMapper().writeValueAsString(goods), XContentType.JSON);
            bulkRequest.add(indexRequest);
        }

        BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        if (bulkResponse.hasFailures()) {
            log.info("Failed to save some goods data: " + bulkResponse.buildFailureMessage());
        } else {
            log.error("All goods data saved successfully.");
        }
        log.info("商品索引文档初始化成功");
    }

}

